package de.koller.worlders.engine.util.tilebased;

import java.util.HashSet;
import java.util.Set;

public class LineWay {

	private final float sx, sy, dx, dy;
	
	private LineWay( float sx, float sy, float dx, float dy ) {
		this.sx = sx;
		this.sy = sy;
		this.dx = dx;
		this.dy = dy;
	}
	
	public static Set<TilePos> allTilesOnLine( float sx, float sy, float dx, float dy ) {
		return new LineWay( sx, sy, dx, dy ).calcAllTilesOnLine();
	}

	private Set<TilePos> calcAllTilesOnLine() {
		Set<TilePos> t = new HashSet<>();
		addVertCont( t );
		addHoriCont( t );
		return t;
	}
	
	private void addVertCont( Set<TilePos> container ) {
		float fy = (float)Math.floor( Math.min( sy, dy ) ) + 1;
		float ty = (float)Math.floor( Math.max( sy, dy ) );
		
		if( fy >= ty )
			return;
		
		for( float y = fy; y < ty; y++ ) {
			float x = (float)Math.floor( getXAt( y ) );
			container.add( new TilePos( (int)x, (int)y-1 ) );
			container.add( new TilePos( (int)x, (int)y ) );
		}
	}
	
	private void addHoriCont( Set<TilePos> container ) {
		float fx = (float)Math.floor( Math.min( sx, dx ) ) + 1;
		float tx = (float)Math.floor( Math.max( sx, dx ) );

		if( fx >= tx )
			return;
		
		for( float x = fx; x < tx; x++ ) {
			float y = (float)Math.floor( getYAt( x ) );
			container.add( new TilePos( (int)x-1, (int)y ) );
			container.add( new TilePos( (int)x, (int)y ) );
		}		
	}
	
	private float getXAt( float y ) {
		if( y == sy )
			return sx;
		
		float fy = y - sy;
		float s = Math.abs( ( dy - sy ) / fy );
		float x = (dx-sx) / s;
		return sx + x;
	}
	
	private float getYAt( float x ) {
		if( x == sx )
			return sy;
		
		float fx = x - sx;
		float s = Math.abs( ( dx - sx ) / fx );
		float y = (dy-sy) / s;
		return sy + y;
	}
	
}
